using System;
using FluentParser;
using FluentParser.Expressions.Rules.Composition;

namespace FluentParser.Editor.Grammars
{
    public class MathGrammarWithErrorRecovery : Grammar<int>
    {
        public MathGrammarWithErrorRecovery()
        {
            // Errors
            var errorEndOfText = Errors.SymbolFatal("Expected end of text");
            var errorInvalid = Errors.Fatal<int>("Invalid expression");
            var errorExpectedExpression = Errors.Fatal<int>("Expected expression");

            // Tokens
            var item = FutureRule<int>();
            var number = ParseString.Regex("-?[0-9]+").Convert<int>(Int32.Parse);
            var spaces = ParseSymbol.Regex("[ \r\n\t]*");
            var parenthesis = item.Surround(spaces).Surround("(", ")");
            var numberOrParenthesis = parenthesis | number | errorExpectedExpression;
            var operators = ParseOperators(numberOrParenthesis, spaces)
                .Register("MOD", "%", (x, y) => x % y)
                .Register("MUL", "*", (x, y) => x * y)
                .Register("DIV", "/", (x, y) => x / y)
                .Register("ADD", "+", (x, y) => x + y)
                .Register("SUB", "-", (x, y) => x - y)
                .Group(GroupingOrientation.LeftToRight, "MOD")
                .Group(GroupingOrientation.LeftToRight, "MUL", "DIV")
                .Group(GroupingOrientation.LeftToRight, "ADD", "SUB");

            item.Source = operators;

            Root = item.Surround(spaces) + (EndOfText | errorEndOfText);
        }
    }
}